#ifndef __tenacitas_log_core__level__h__
#define __tenacitas_log_core__level__h__



/** @file
    In this file is implemented tenacitas::log::level class */


/** todo */

// ==> C++ Headers
#include <cstdint>
#include <string>
#include <sstream>

// ==> 3rds Headers

// ==> Our Headers
#include <tenacitas.return_code.core/rc.h>

// ==> Namespaces
using namespace std;

// ==> Macro Constants

// ==> Macro Commands


/** namespace of the organization */
namespace tenacitas {

    /** ==> namespace of the project */
    namespace log {

        namespace core {

            // ==> Typedefs 

            // ==> Pre-Declarations

            // ==> Attributes 

            // ==> Functions
        
            // ==> Classes

            /** Levels for logging messages

                There are 6 levels of logging defined: trace, debug, info, warn, error
                and fatal. @p trace is the lowest and @p fatal is the highest
                level. @p fatal calls @p exit, causing the program to stop.

                <b>A word to the programmer user</b>
                You should use the tenacitas::log::level::trace,
                tenacitas::log::level::debug, tenacitas::log::level::info,
                tenacitas::log::level::warn, tenacitas::log::level::error or
                tenacitas::log::level::fatal objects to define the log level
                you want to use.
                @nosubgrouping 
            */
            class level {

            public:

                //  ==> level - Friends

                /** << operator */
                friend std::ostream & operator << (std::ostream & p_out,
                                            const level & p_level) {
                    p_out << p_level.str();
                    return p_out;
                }
                

                //  ==> level - Public Constructors

                /** Copy constructor */
                level( const level & p_level );

                level( );

                level( level && p_level ) ;

                /** Destructor */
                inline ~level( );

                //  ==> level - Public Accessors 

                /** Informs a string corresponding a log level object */
                inline std::string str( ) const;

                //  ==> level - Public Cores -

                /** Creates a log level object based on a string */
                inline static const level & create( const std::string & p_str );

                //  ==> level - Public Operators 

                /** assignment */
                inline level & operator = ( const level & p_level );

                /** equal-to */
                inline bool operator == ( const level & p_level ) const;            

                /** not-equal-to */
                inline bool operator != ( const level & p_level ) const;
            
                /** greater-than-or-equal-to */
                inline bool operator >= ( const level & p_level ) const;

                /** greater-than not allowed */
                inline bool operator > ( const level & ) const = delete;

                /** less-than-or-equal-to */
                inline bool operator <= ( const level & p_level ) const;

                /** less-than not allowed */
                inline bool operator < ( const level & ) const = delete;

                //  ==> level - Public Attributes -

                /** Only posssibe log level values - trace */
                static const level trace;

                /** Only posssibe log level values - debug */
                static const level debug;

                /** Only posssibe log level values - info */
                static const level info;

                /** Only posssibe log level values - warn */
                static const level warn;

                /** Only posssibe log level values - error */
                static const level error;

                /** Only posssibe log level values - fatal */
                static const level fatal;

            private:
                //  ==> level - Public Internal Types

                /** Type for the internal level of the log */
                typedef int16_t value;

                //  ==> level - Private Constructors

                /** Constructor */
                level( value p_value )
                    : m_value( p_value ) { }

                //  ==> level - Private Attributes 

                /** numeric value for a log level */
                value m_value;
            };
        }
    }
}

// =============================================================================
//                     I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::log::core;


// -----------------------------------------------------------------------------
inline level::
level( )
    : m_value(level::info.m_value){}

// -----------------------------------------------------------------------------
inline level::
level( level && p_level )
    : m_value( std::move(p_level.m_value) ) {}

// -----------------------------------------------------------------------------
inline level::
level( const level & p_level )
    : m_value( p_level.m_value ) {}
            
// -----------------------------------------------------------------------------
inline level::
~level( ) {}

// -----------------------------------------------------------------------------
std::string
level::
str( ) const {
    if ( m_value == trace.m_value ) { return "TRACE"; }
    if ( m_value == debug.m_value ) { return "DEBUG"; }
    if ( m_value == info.m_value ) { return "INFO"; }
    if ( m_value == warn.m_value ) { return "WARN"; }
    if ( m_value == error.m_value ) { return "ERROR"; }
    if ( m_value == fatal.m_value ) { return "FATAL"; }

    return "";
}

// -----------------------------------------------------------------------------
const level &
level::
create( const std::string & p_str ) {
    if ( p_str == "trace" ) { return trace; }
    if ( p_str == "debug" ) { return debug; }
    if ( p_str == "info" ) { return info; }
    if ( p_str == "warn" ) { return warn; }
    if ( p_str == "error" ) { return error; }
    if ( p_str == "fatal" ) { return fatal; }
    
    return info;
}

// -----------------------------------------------------------------------------
level &
level::
operator = ( const level & p_level ) {
    if ( this != & p_level ) {
        m_value = p_level.m_value;
    }
    return *this;
}

// -----------------------------------------------------------------------------
bool
level::
operator == ( const level & p_level ) const {
    return m_value == p_level.m_value;
}

// -----------------------------------------------------------------------------
bool
level::
operator != ( const level & p_level ) const {
    return m_value != p_level.m_value;
}

// -----------------------------------------------------------------------------
bool
level::
operator >= ( const level & p_level ) const {
    return m_value >= p_level.m_value;
}

// -----------------------------------------------------------------------------
bool
level::
operator <= ( const level & p_level ) const {
    return m_value <= p_level.m_value;
}


#endif
// end 
